package com.zpz.framework.zpzoauth.config.oauth.authorization.exouath.authenticator.partner.zhy;

import com.alibaba.fastjson.JSON;
import com.zpz.framework.zpzoauth.common.encrypt.sm4.SM4Utils;
import com.zpz.framework.zpzoauth.common.result.ZpzOauthResultMsg;
import com.zpz.framework.zpzoauth.common.result.ZpzOauthResultStatus;
import com.zpz.framework.zpzoauth.common.utils.ZpzOauthHttpUtil;
import com.zpz.framework.zpzoauth.config.oauth.authorization.exouath.ZpzOauthIntegrationAuthentication;
import com.zpz.framework.zpzoauth.config.oauth.authorization.exouath.authenticator.AbstractPreparableIntegrationAuthenticator;
import com.zpz.framework.zpzoauth.dao.ZpzOauthFrameUserMapper;
import com.zpz.framework.zpzoauth.pojo.po.FrameUser;
import com.zpz.framework.zpzoauth.pojo.qo.ModifyUserLoginDateQo;
import com.zpz.framework.zpzoauth.pojo.vo.UserAuthenticationVo;
import com.zpz.framework.zpzoauth.service.ZpzOauthFrameUserService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Primary;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author zhangpanzhi
 * @time 2019-07-09
 * @description 未经本人允许请勿随便改动，尊重劳动
 * */
@Component
@Primary
public class ZpzOauthCsLoginAuthenticator extends AbstractPreparableIntegrationAuthenticator {
    private Logger log = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private ZpzOauthFrameUserService zpzOauthFrameUserService;
    @Resource
    private ZpzOauthFrameUserMapper zpzOauthFrameUserMapper;
    @Value("${zpzOauth.partner}")
    private String partner;
    private final static String U_P_AUTH_TYPE = "zhy_cs_login";
    @Override
    public UserAuthenticationVo authenticate(ZpzOauthIntegrationAuthentication zpzOauthIntegrationAuthenticator) {
        log.info("中海油CS登录：入参："+ JSON.toJSONString(zpzOauthIntegrationAuthenticator));
        Map<String,Object> partnerStr = (Map<String, Object>) JSON.parse(partner);
        Object zhy = partnerStr.get("zhy");
        if (zhy==null){
            throw new OAuth2Exception("登录授权失败[ZPZ_DEFINED_OAUTH2_EXCEPTION]["+ ZpzOauthResultStatus.DIY_ERROR__1010.getCode() +"]系统参数配置错误，请联系管理员");
        }
        Map<String,Object> zhyStr = (Map<String, Object>) JSON.parse(zhy.toString());
        String tokenUrl = (String)zhyStr.get("tokenUrl");
        String sm4Key = (String)zhyStr.get("sm4Key");
        String appId = (String)zhyStr.get("appId");
        String userInfoUrl=(String)zhyStr.get("userInfoUrl");
        String password = zpzOauthIntegrationAuthenticator.getAuthParameter("password");
        SM4Utils pwdSm4=new SM4Utils();
        pwdSm4.secretKey=sm4Key;
        Map<String,String> param=new HashMap<>();
        param.put("appId",appId);
        param.put("j_username",zpzOauthIntegrationAuthenticator.getUsername());
        param.put("j_password",pwdSm4.encryptData_ECB(password));
        param.put("sms_checkcode",zpzOauthIntegrationAuthenticator.getAuthParameter("smsCode"));
        param.put("remoteIp",zpzOauthIntegrationAuthenticator.getAuthParameter("remoteIp"));
        log.info(String.format("%s------请求参数------%s",tokenUrl,JSON.toJSONString(param)));
        String res = null;
        try {
            res = ZpzOauthHttpUtil.getInstance().doGetForString(tokenUrl, param);
            log.info(String.format("响应数据------%s",res));
        }catch (Exception e) {
            throw new OAuth2Exception("登录授权失败[ZPZ_DEFINED_OAUTH2_EXCEPTION]["+ ZpzOauthResultStatus.DIY_ERROR__1010.getCode() +"]认证失败");
        }
        if (!StringUtils.isNotBlank(res)){
            throw new OAuth2Exception("登录授权失败[ZPZ_DEFINED_OAUTH2_EXCEPTION]["+ ZpzOauthResultStatus.DIY_ERROR__1010.getCode() +"]认证失败");
        }
        Map<String,Object> resData=(Map<String, Object>) JSON.parse(res);
        Object message = resData.get("message");
        log.info(String.format("响应信息--------------%s",message));
        if (message!=null){
            Map<String,Object>map=(Map<String, Object>) JSON.parse(message.toString());
            Object name = map.get("name");
            if (name!=null){
                String nameres=name.toString();
                log.info(String.format("响应信息-nameres-------------%s",nameres));
                if (nameres.equals("com.bamboocloud.am.rest.Authenticate")){
                    throw new OAuth2Exception("登录授权失败[ZPZ_DEFINED_OAUTH2_EXCEPTION]["+ ZpzOauthResultStatus.DIY_ERROR__1010.getCode() +"]认证请求参数不完整");
                } else if (nameres.equals("com.bamboocloud.am.rest.Authenticate")){
                    throw new OAuth2Exception("登录授权失败[ZPZ_DEFINED_OAUTH2_EXCEPTION]["+ ZpzOauthResultStatus.DIY_ERROR__1010.getCode() +"]"+map.get("content").toString());
                } else if (nameres.equals("login.form.error.unsupported_appId")){
                    throw new OAuth2Exception("登录授权失败[ZPZ_DEFINED_OAUTH2_EXCEPTION]["+ ZpzOauthResultStatus.DIY_ERROR__1010.getCode() +"]appId对应认证链验证不通过");
                } else if (nameres.equals("login.form.error.smsCheckCode.invalidNumber")){
                    throw new OAuth2Exception("登录授权失败[ZPZ_DEFINED_OAUTH2_EXCEPTION]["+ ZpzOauthResultStatus.DIY_ERROR__1010.getCode() +"]短信校验码不正确");
                } else if (nameres.equals("login.form.error.userpass.invalidNumber")){
                    throw new OAuth2Exception("登录授权失败[ZPZ_DEFINED_OAUTH2_EXCEPTION]["+ ZpzOauthResultStatus.DIY_ERROR__1010.getCode() +"]用户、密码或验证码不正确");
                } else if (nameres.equals("login.form.error.username.locked")){
                    throw new OAuth2Exception("登录授权失败[ZPZ_DEFINED_OAUTH2_EXCEPTION]["+ ZpzOauthResultStatus.DIY_ERROR__1010.getCode() +"]用户锁定");
                } else if (nameres.equals("login.form.error.username.isDisabled")){
                    throw new OAuth2Exception("登录授权失败[ZPZ_DEFINED_OAUTH2_EXCEPTION]["+ ZpzOauthResultStatus.DIY_ERROR__1010.getCode() +"]用户被禁用");
                } else if (nameres.equals("login.form.error.username.notMatchAuthed")){
                    throw new OAuth2Exception("登录授权失败[ZPZ_DEFINED_OAUTH2_EXCEPTION]["+ ZpzOauthResultStatus.DIY_ERROR__1010.getCode() +"]一个会话登陆不同账号");
                } else if (nameres.equals("login.form.error.password.modifyPassword")){
                    throw new OAuth2Exception("登录授权失败[ZPZ_DEFINED_OAUTH2_EXCEPTION]["+ ZpzOauthResultStatus.DIY_ERROR__1010.getCode() +"]需要修改密码");
                } else if (nameres.equals("login.form.error.password.expired")){
                    throw new OAuth2Exception("登录授权失败[ZPZ_DEFINED_OAUTH2_EXCEPTION]["+ ZpzOauthResultStatus.DIY_ERROR__1010.getCode() +"]密码过期");
                } else if (nameres.equals("login.form.error.username.firstLogin")){
                    throw new OAuth2Exception("登录授权失败[ZPZ_DEFINED_OAUTH2_EXCEPTION]["+ ZpzOauthResultStatus.DIY_ERROR__1010.getCode() +"]首次登陆需要修改密码");
                } else if (nameres.equals("login.form.error.password.passwordQuestion")){
                    throw new OAuth2Exception("登录授权失败[ZPZ_DEFINED_OAUTH2_EXCEPTION]["+ ZpzOauthResultStatus.DIY_ERROR__1010.getCode() +"]需要完善密保问题");
                }
            }
        }
        Object dataObj = resData.get("data");
        if (dataObj==null){
            throw new OAuth2Exception("登录授权失败[ZPZ_DEFINED_OAUTH2_EXCEPTION]["+ ZpzOauthResultStatus.DIY_ERROR__1010.getCode() +"]获取用户信息失败");
        }
        Map<String,Object> s = (Map<String, Object>) JSON.parse(dataObj.toString());
        Object tokenId = s.get("tokenId");
        if (tokenId==null){
            throw new OAuth2Exception("登录授权失败[ZPZ_DEFINED_OAUTH2_EXCEPTION]["+ ZpzOauthResultStatus.DIY_ERROR__1010.getCode() +"]获取用户信息失败");
        }
        // 获取用户信息
        String userInfoRes = null;
        Map<String,String> userInfoParam=new HashMap<>();
        userInfoParam.put("appId",appId);
        userInfoParam.put("tokenId",tokenId.toString());
        userInfoParam.put("remoteIp",zpzOauthIntegrationAuthenticator.getAuthParameter("remoteIp"));
        log.info(String.format("%s-----------请求数据--------%s",userInfoUrl, JSON.toJSONString(userInfoParam)));
        try {
            userInfoRes = ZpzOauthHttpUtil.getInstance().doGetForString(userInfoUrl, userInfoParam);
            log.info(String.format("响应数据-------%s",userInfoRes));
        }catch (Exception e) {
            throw new OAuth2Exception("登录授权失败[ZPZ_DEFINED_OAUTH2_EXCEPTION]["+ ZpzOauthResultStatus.DIY_ERROR__1010.getCode() +"]获取用户信息失败");
        }
        if (!StringUtils.isNotBlank(userInfoRes)){
            throw new OAuth2Exception("登录授权失败[ZPZ_DEFINED_OAUTH2_EXCEPTION]["+ ZpzOauthResultStatus.DIY_ERROR__1010.getCode() +"]获取用户信息失败");
        }
        Map<String,Object> uiData=(Map<String, Object>) JSON.parse(userInfoRes);
        Object uidataObj = uiData.get("data");
        if (uidataObj==null){
            throw new OAuth2Exception("登录授权失败[ZPZ_DEFINED_OAUTH2_EXCEPTION]["+ ZpzOauthResultStatus.DIY_ERROR__1010.getCode() +"]获取用户信息失败");
        }
        log.info(String.format("响应数据data-------%s",uidataObj.toString()));
        Map<String,Object> uis = (Map<String, Object>) JSON.parse(uidataObj.toString());
        Object attributes = uis.get("attributes");
        if (attributes==null){
            throw new OAuth2Exception("登录授权失败[ZPZ_DEFINED_OAUTH2_EXCEPTION]["+ ZpzOauthResultStatus.DIY_ERROR__1010.getCode() +"]获取用户信息失败");
        }
        log.info(String.format("响应数据attributes-------%s",attributes.toString()));
        Map<String,Object> attributesMap = (Map<String, Object>) JSON.parse(attributes.toString());
        Object loginName = attributesMap.get("loginName");
        if (loginName==null){
            throw new OAuth2Exception("登录授权失败[ZPZ_DEFINED_OAUTH2_EXCEPTION]["+ ZpzOauthResultStatus.DIY_ERROR__1010.getCode() +"]获取用户信息失败");
        }
        log.info(String.format("响应数据loginName-------%s",loginName.toString()));
        UserAuthenticationVo data = null;
        try {
            FrameUser zu=new FrameUser();
            zu.setUserName(loginName.toString());
            zu.setDelFlag(0);
            List<FrameUser> list = zpzOauthFrameUserMapper.select(zu);
            log.info(String.format("查询数据------%s",list!=null?JSON.toJSONString(list):0));
            if (list==null||list.size()==0){
                throw new OAuth2Exception("登录授权失败[ZPZ_DEFINED_OAUTH2_EXCEPTION]["+ ZpzOauthResultStatus.DIY_ERROR__1010.getCode() +"]用户信息没有同步，请联系管理员");
            }
            FrameUser frameUser = list.get(0);
            data = new UserAuthenticationVo();
            data.setUserCode(frameUser.getUserCode());
            data.setPassword(passwordEncoder.encode(password));
            data.setStatus(frameUser.getStatus());
            ModifyUserLoginDateQo t=new ModifyUserLoginDateQo();
            t.setUserCode(data.getUserCode());
            t.setClientId(zpzOauthIntegrationAuthenticator.getClientId());
            t.setLoginDate(new Date());
            ZpzOauthResultMsg<Boolean> flag = zpzOauthFrameUserService.modifyUserLoginDate(t);
            log.info("::::::::::修改最新登录时间："+JSON.toJSONString(flag));
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage(),e);
        }
        log.info(String.format("返回数据------",JSON.toJSONString(data)));
        return data;
    }

    @Override
    public void prepare(ZpzOauthIntegrationAuthentication integrationAuthentication) {

    }

    @Override
    public boolean support(ZpzOauthIntegrationAuthentication integrationAuthentication) {
    	//增加空判断，支持授权码模式
        return StringUtils.isEmpty(integrationAuthentication.getAuthType())
        		||U_P_AUTH_TYPE.equals(integrationAuthentication.getAuthType());
    }
}
